<?php

require_once(dirname(__FILE__) . '/Task.php');

/**
 * Description of DWebBrowserEvents2
 * Unstable Class, because work with IE COM
 * The most stable work with IE8
 *
 * @author Gvozd
 */
class DWebBrowserEvents2 extends Task {

    /**
     *
     * @var array list of active ie
     */
    private static $ies = null;

    /**
     *
     * @var COM ie 
     */
    public $ie;
    public $terminated = false;

    public function __construct($url) {
        $this->url = $url;
    }

    public function startExecution() {
        if (null === self::$ies) {
            self::$ies = array();
            Tick::getInstance()->addEventListener('tick', array(__CLASS__, 'comMessagePump'));
        }
        try {
            $ie = new COM("InternetExplorer.Application");
            $this->Visible = $ie->Visible = false;
            $ie->Navigate2($this->url);
            com_event_sink($ie, $this, "DWebBrowserEvents2");

            self::$ies[] = $ie;
            $this->ie = $ie;
        } catch (DieException $e) {
            echo 'Caught exception: ', $e->getMessage(), "\n";
            $this->OnQuit();
        }

        $this->addEventListener('progresschange', array($this, 'onActivityFixed'));
    }

    public function onActivityFixed($event) {
        $command = $event->params[0];
        $enable = $event->params[1];
        if (!($command == 0 && $enable == 0 && !$this->ie->Busy)) {
            return;
        }
        static $timeout = null;
        clearTimeout($timeout);
        if ($this->terminated)
            return;
        $timeout = setTimeout(array($this, 'onEnded'), 2);
    }

    public function onEnded() {
        $this->removeEventListener('progresschange', $this->onActivityFixed);
        if ($this->terminated)
            return;
        $this->dispatchEvent(new Event('onLoad'));

        if (!$this->Visible) {
            try {
                if (method_exists($this->ie, 'Quit')) {
                    $this->ie->Quit();
                } else {
                    throw new DieException('Unexist method Quit');
                }
            } catch (DieException $e) {
                echo 'Caught exception: ', $e->getMessage(), "\n";
                $this->OnQuit();
            }
        }
    }

    /**
     *
     * @param <type> $name
     * @param <type> $arguments
     */
    public function __call($name, $arguments) {
        $event = new Event($name);
        $event->setParams($arguments);
        $this->dispatchEvent($event);
        if (strtolower($name) !== $name) {
            $event = new Event(strtolower($name));
            $event->setParams($arguments);
            $this->dispatchEvent(strtolower($event));
        }

        $event = new Event('onActivityFixed');
        $this->dispatchEvent($event);

        if (strtolower($name) != 'onvisible') {
            //$this->ie->Visible = true;
            //$this->ie->Visible = $this->Visible;
        }
        //$this->last_time_called = microtime(true);
    }

    public function OnQuit() {
        $keys = array();
        foreach (self::$ies as $key => $ie) {
            if ($ie === $this->ie) {
                $keys[] = $key;
            }
        }
        foreach ($keys as $key) {
            unset(self::$ies[$key]);
        }
        $this->terminated = true;
        $this->dispatchEvent(new Event('taskEnded'));
    }

    /**
     *
     * @param Event $event
     */
    public static function comMessagePump($event) {
        usleep(10000);
        global $queue;
        if (!$queue->hasExecuted()) {
            $event->target->removeEventListener($event->type, $event->callee);
            global $timer_out;
            clearTimeout($timer_out);
        } else {
            try {
                com_message_pump();
            } catch (DieException $e) {
                echo 'Caught exception: ', $e->getMessage(), "\n";
            }
        }
    }

}
